#pragma once

#include <math.h>

#define V2DI clkVec2<int>
#define V2DF clkVec2<float>

template <typename TYPE>
struct clkVec2
{
	TYPE x, y;

	clkVec2()
	{x=y=0;}

	clkVec2(TYPE av)
	{x=y=av;}

	clkVec2(TYPE ax, TYPE  ay)
	{x=ax;y=ay;}

	clkVec2(clkVec2<TYPE>& av)
	{x=av.x;y=av.y;}

	void operator=(TYPE av)
	{x=y=av;}

	void operator=(clkVec2<TYPE>& av)
	{x=av.x;y=av.y;}

	TYPE operator[](int av)
	{return (av==0)?x:(av==1)?y:0;}

	clkVec2<TYPE> operator-()
	{return clkVec2<TYPE>(-x,-y);}

	clkVec2<TYPE> operator+(const clkVec2<TYPE>& av)
	{return clkVec2<TYPE>(x+av.x,y+av.y);}

	clkVec2<TYPE> operator-(const clkVec2<TYPE>& av)
	{return clkVec2<TYPE>(x-av.x,y-av.y);}

	clkVec2<TYPE> operator*(const clkVec2<TYPE>& av)
	{return clkVec2<TYPE>(x*av.x,y*av.y);}

	clkVec2<TYPE> operator/(const clkVec2<TYPE>& av)
	{return clkVec2<TYPE>((av.x!=0)?x/av.x:0,(av.y!=0)?y/av.y:0);}

	clkVec2<TYPE> operator+(const TYPE& av)
	{return clkVec2<TYPE>(x+av,y+av);}

	clkVec2<TYPE> operator-(const TYPE& av)
	{return clkVec2<TYPE>(x-av,y-av);}

	clkVec2<TYPE> operator*(const TYPE& av)
	{return clkVec2<TYPE>(x*av,y*av);}

	clkVec2<TYPE> operator/(const TYPE& av)
	{return (av!=0)?clkVec2<TYPE>(x/av,y/av):clkVec2<TYPE>();}

	void operator+=(const clkVec2<TYPE>& av)
	{x+=av.x;y+=av.y;}

	void operator-=(const clkVec2<TYPE>& av)
	{x-=av.x;y-=av.y;}

	void operator*=(const clkVec2<TYPE>& av)
	{x*=av.x;y*=av.y;}

	void operator/=(const clkVec2<TYPE>& av)
	{(av.x!=0)?x/=av.x:x=0;(av.y!=0)?y/=av.y:y=0;}

	void operator+=(const TYPE& av)
	{x+=av;y+=av;}

	void operator-=(const TYPE& av)
	{x-=av;y-=av;}

	void operator*=(const TYPE& av)
	{x*=av;y*=av;}

	void operator/=(const TYPE& av)
	{if(av!=0){x/=av;y/=av;}else{x=0;y=0;}}

	friend clkVec2<TYPE> operator+(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return clkVec2<TYPE>(avA+avB.x,avA+avB.y);}

	friend clkVec2<TYPE> operator-(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return clkVec2<TYPE>(avA-avB.x,avA-avB.y);}

	friend clkVec2<TYPE> operator*(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return clkVec2<TYPE>(avA*avB.x,avA*avB.y);}

	friend clkVec2<TYPE> operator/(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return (avA!=0)?clkVec2<TYPE>((avB.x!=0)?avA/avB.x:0,(avB.y!=0)?avA/avB.y:0):clkVec2<TYPE>();}

	friend clkVec2<TYPE> operator+=(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return clkVec2<TYPE>(avA+avB.x,avA+avB.y);}

	friend clkVec2<TYPE> operator-=(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return clkVec2<TYPE>(avA-avB.x,avA-avB.y);}

	friend clkVec2<TYPE> operator*=(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return clkVec2<TYPE>(avA*avB.x,avA*avB.y);}

	friend clkVec2<TYPE> operator/=(const TYPE& avA, const clkVec2<TYPE>& avB)
	{return (avA!=0)?clkVec2<TYPE>((avB.x!=0)?avA/avB.x:0,(avB.y!=0)?avA/avB.y:0):clkVec2<TYPE>();}

	bool operator<(const clkVec2<TYPE>& av)
	{return (x<av.x&&y<av.y)?true:false;}

	bool operator>(const clkVec2<TYPE>& av)
	{return (x>av.x&&y>av.y)?true:false;}

	bool operator<=(const clkVec2<TYPE>& av)
	{return (x<=av.x&&y<=av.y)?true:false;}

	bool operator>=(const clkVec2<TYPE>& av)
	{return (x>=av.x&&y>=av.y)?true:false;}

	bool operator==(const clkVec2<TYPE>& av)
	{return (x==av.x&&y==av.y)?true:false;}

	bool operator!=(const clkVec2<TYPE>& av)
	{return (x!=av.x&&y!=av.y)?true:false;}

	bool zeroed()
	{return x==0&&y==0;}

	void set(TYPE av)
	{x=y=av;}

	void set(TYPE ax, TYPE ay)
	{x=ax;y=ay;}

	void set(clkVec2<TYPE> av)
	{x=av.x;y=av.y;}

	void zero()
	{x=y=0;}

	void negate()
	{x=-x;y=-y;}

	TYPE distance(clkVec2<TYPE> av)
	{return sqrt(distanceSq(av));}

	TYPE distanceSq(clkVec2<TYPE> av)
	{TYPE dx=x-av.x,dy=y-av.y; return (dx*dx)+(dy*dy);}

	TYPE dot(clkVec2<TYPE> av)
	{return (x*av.x)+(y*av.y);}

	TYPE magnitude()
	{return sqrt(magnitudeSq());}

	TYPE magnitudeSq()
	{return (x*x)+(y*y);}

	clkVec2<TYPE> normal()
	{clkVec2<TYPE> n=*this;n.normalize();return n;}

	clkVec2<TYPE> normalize()
	{float m=magnitude();if(m!=0){if(x!=0)x/=m;if(y!=0)y/=m;}return *this;}

	clkVec2<TYPE> perp()
	{return clkVec2<TYPE>(-y,x);}
};